package com.ruoyi.demo.config;

import cn.smallbun.screw.core.Configuration;
import cn.smallbun.screw.core.engine.EngineConfig;
import cn.smallbun.screw.core.engine.EngineFileType;
import cn.smallbun.screw.core.engine.EngineTemplateType;
import cn.smallbun.screw.core.execute.DocumentationExecute;
import cn.smallbun.screw.core.process.ProcessConfig;
import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties;
import com.baomidou.mybatisplus.core.toolkit.AES;
import com.dyun.tool.jwt.prop.SecureProperties;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import lombok.AllArgsConstructor;
import net.dreamlu.mica.core.utils.$;
import org.jasypt.encryption.StringEncryptor;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Profile;

import javax.sql.DataSource;
import java.util.ArrayList;
import java.util.Date;

/**
 * 文章地址：
 * <p>
 * 数据库设计文档生成：https://juejin.im/post/6854573221224644622
 * 配置文件加密：https://juejin.im/post/6844904178251218952
 *
 * @author dyun
 */
//@org.springframework.context.annotation.Configuration
@AllArgsConstructor
public class DatabaseDocConfig {

    private final DataSourceProperties dataSourceProperties;

    private final StringEncryptor stringEncryptor;

    private final RedisProperties redisProperties;

    private final DruidStatProperties druidStatProperties;

    private final SecureProperties secureProperties;

    @Bean
    @Profile({"dev", "test"})
    public void DyDatabaseDoc() {

        System.out.println("=============================数据库加密配置开始=============================");
        // 生成 16 位随机 AES 密钥
        String nextSalt = AES.generateRandomKey();
        System.out.println("nextSalt:" + nextSalt);

        // 随机密钥加密
        String salt = "555530e3440612343";
        System.out.println("salt:" + salt);
        // mybatisplus加密
//        String jdbcUrl = AES.encrypt(dataSourceProperties.getUrl(), salt);
//        String userName = AES.encrypt(dataSourceProperties.getUsername(), salt);
//        String password = AES.encrypt(dataSourceProperties.getPassword(), salt);
//        System.out.println("url: mpw:" + jdbcUrl);
//        System.out.println("username: mpw:" + userName);
//        System.out.println("password: mpw:" + password);
//        // Jar 启动参数（ idea 设置Program arguments 程序参数 , 服务器可以设置为启动环境变量 ）
//        System.out.println("启动添加: --mpw.key=" + nextSalt);
        // 通用jasypt加密
        String jdbcUrl = stringEncryptor.encrypt(dataSourceProperties.getUrl());
        String userName = stringEncryptor.encrypt(dataSourceProperties.getUsername());
        String password = stringEncryptor.encrypt(dataSourceProperties.getPassword());
        System.out.println("url: ENC(" + jdbcUrl + ")");
        System.out.println("username: ENC(" + userName + ")");
        System.out.println("password: ENC(" + password + ")");
        // Jar 启动参数（ idea 设置 Program arguments , 服务器可以设置为启动环境变量 ）
        System.out.println("启动时设置程序参数: --jasypt.encryptor.password=" + salt);
        System.out.println("=============================数据库加密配置结束=============================");
        printYamlConfig();

        //数据源
        HikariConfig hikariConfig = new HikariConfig();
        hikariConfig.setDriverClassName(dataSourceProperties.getDriverClassName());
        hikariConfig.setJdbcUrl(dataSourceProperties.getUrl());
        hikariConfig.setUsername(dataSourceProperties.getUsername());
        hikariConfig.setPassword(dataSourceProperties.getPassword());
        //设置可以获取tables remarks信息
        hikariConfig.addDataSourceProperty("useInformationSchema", "true");
        hikariConfig.setMinimumIdle(2);
        hikariConfig.setMaximumPoolSize(5);
        DataSource dataSource = new HikariDataSource(hikariConfig);
        //生成配置
        EngineConfig engineConfig = EngineConfig.builder()
                //生成文件路径
                .fileOutputDir("/Users/dyun")
                //打开目录
                .openOutputDir(true)
                //文件类型
                .fileType(EngineFileType.HTML)
                //生成模板实现
                .produceType(EngineTemplateType.freemarker).build();

        //忽略表
        ArrayList<String> ignoreTableName = new ArrayList<>();
        ignoreTableName.add("test_user");
        ignoreTableName.add("test_group");
        //忽略表前缀
        ArrayList<String> ignorePrefix = new ArrayList<>();
        ignorePrefix.add("test_");
        ignorePrefix.add("qrtz_");
        //忽略表后缀
        ArrayList<String> ignoreSuffix = new ArrayList<>();
        ignoreSuffix.add("_test");
        ProcessConfig processConfig = ProcessConfig.builder()
                //忽略表名
                .ignoreTableName(ignoreTableName)
                //忽略表前缀
                .ignoreTablePrefix(ignorePrefix)
                //忽略表后缀
                .ignoreTableSuffix(ignoreSuffix).build();
        //配置
        Configuration config = Configuration.builder()
                //版本
                .version($.formatDate(new Date()))
                //描述
                .description("数据库设计文档生成")
                //数据源
                .dataSource(dataSource)
                //生成配置
                .engineConfig(engineConfig)
                //生成配置
                .produceConfig(processConfig).build();
        //执行生成
        new DocumentationExecute(config).execute();
    }

    private void printYamlConfig() {
        System.out.println("=============================Druid配置开始=============================");
        System.out.println("login-username: ENC(" + stringEncryptor.encrypt(druidStatProperties.getStatViewServlet().getLoginUsername()) + ")");
        System.out.println("login-password: ENC(" + stringEncryptor.encrypt(druidStatProperties.getStatViewServlet().getLoginPassword()) + ")");
        System.out.println("=============================Druid配置结束=============================");
        System.out.println("=============================extend.secure配置开始=============================");
        System.out.println("sign-key: ENC(" + stringEncryptor.encrypt(secureProperties.getSignKey()) + ")");
        System.out.println("=============================extend.secure配置结束=============================");
        System.out.println("=============================redis配置开始=============================");
        System.out.println("host: ENC(" + stringEncryptor.encrypt(redisProperties.getHost()) + ")");
        System.out.println("password: ENC(" + stringEncryptor.encrypt(redisProperties.getPassword()) + ")");
        System.out.println("=============================redis配置结束=============================");
    }

}
